#include "PcoDecoder.h"
#include <map>

#define NAME L"Pco"

ColumnHalfDecoder::ColumnHalfDecoder()
{
	_name = wstring(NAME);
	_err = wstring(L"NONE");
}
ColumnHalfDecoder::~ColumnHalfDecoder()
{
}
bool ColumnHalfDecoder::Inited()
{
	return true;
}

void ColumnHalfDecoder::Close()
{
	delete this;
}

int ColumnHalfDecoder::Decode(unsigned char *dest, int dest_buf_len, unsigned char *source, int color_depth, int column, int line, DecodeRequestStruct* args/* = 0*/)
{
	int pix_num = column * line;
	unsigned char *tmp_source = (unsigned char *)malloc(column * line * ((color_depth + 7) / 8));
	unsigned char *tmp_source1 = (unsigned char *)malloc(pix_num * 3);

	if (tmp_source == NULL || tmp_source1 == NULL)
		return -1;

	if (color_depth == 8) {
	}
	else{
		unsigned short *_s = (unsigned short *)tmp_source;
		unsigned short *_source = (unsigned short *)source;

		for (int i = 0; i < line; i++) {
			if (i % 2 == 0)
				memcpy((unsigned char*)_s + (i / 2 * column) * 2, (unsigned char*)_source + i * column * 2, column * 2);
			else
				memcpy((unsigned char*)_s + (line - 1 - i / 2) * column * 2, (unsigned char*)_source + i * column * 2, column * 2);
		}

		unsigned int max = 0, min = 65535;
		for (int i = 0; i < pix_num; i++){
			max = _s[i] > max ? _s[i] : max;
			min = _s[i] < min ? _s[i] : min;
		}
		if (max == min) max += 1;
		for (int i = 0; i < pix_num; i++){
			tmp_source1[(pix_num - i) * 3 - 1] = tmp_source1[(pix_num - i) * 3 - 2] = tmp_source1[(pix_num - i) * 3 - 3] = 255 * (_s[i] - min) / (max - min);
		}
	}
	if (args->UpDownReverse && args->LeftRightReverse == false)
	{
		for (int i = 0; i < line; i++)
		{
			memcpy(dest + i * column * 3, tmp_source1 + (line - i - 1) * column * 3, column * 3);
		}
	}
	if (args->UpDownReverse == false && args->LeftRightReverse)
	{
		for (int i = 0; i < line; i++)
		{
			for (int j = 0; j < column; j++)
			{
				dest[(column * i + j) * 3 + 0] = tmp_source1[(column * i + (column - 1 - j)) * 3 + 0];
				dest[(column * i + j) * 3 + 1] = tmp_source1[(column * i + (column - 1 - j)) * 3 + 1];
				dest[(column * i + j) * 3 + 2] = tmp_source1[(column * i + (column - 1 - j)) * 3 + 2];
			}
		}
	}
	if (args->UpDownReverse && args->LeftRightReverse)
	{
		for (int i = 0; i < pix_num; i++){
			dest[(pix_num - i) * 3 - 1] = tmp_source1[i * 3];
			dest[(pix_num - i) * 3 - 2] = tmp_source1[i * 3 + 1];
			dest[(pix_num - i) * 3 - 3] = tmp_source1[i * 3 + 2];
		}
	}
	if (args->UpDownReverse == false && args->LeftRightReverse == false)
	{
		memcpy(dest, tmp_source1, pix_num * 3);
	}
	free(tmp_source);
	free(tmp_source1);
	return 0;
}

const wchar_t* ColumnHalfDecoder::Name()
{
	return _name.c_str();
}
const wchar_t* ColumnHalfDecoder::ErrorInfo()
{
	return _err.c_str();
}

void* GetDecoderPlugin(int version)
{
	if (version == DECODER_PLUGIN_INTERFACE_VERSION){
		return new ColumnHalfDecoder();
	} else{
		return NULL;
	}
}